package net.gxf.common.util;

public class ByteBuffer
{

	/* static fields */
	/** 默认的初始容量大小 */
	public static final int CAPACITY=32;
	/** 默认的动态数据或文字的最大长度，400k */
	public static final int MAX_DATA_LENGTH=400*1024;

	/* fields */
	/** 字节数组 */
	byte[] bytes;
	/** 字节缓存的长度 */
	int top;
	/** 字节缓存的偏移量 */
	int offset;

	/* constructors */
	/** 按默认的大小构造一个字节缓存对象 */
	public ByteBuffer()
	{
		this(CAPACITY);
	}
	/** 按指定的大小构造一个字节缓存对象 */
	public ByteBuffer(int capacity)
	{
		if(capacity<1)
			throw new IllegalArgumentException(getClass().getName()
				+" <init>, invalid capatity:"+capacity);
		bytes=new byte[capacity];
		top=0;
		offset=0;
	}
	/** 按指定的字节数组构造一个字节缓存对象 */
	public ByteBuffer(byte[] data)
	{
		if(data==null)
			throw new IllegalArgumentException(getClass().getName()
				+" <init>, null data");
		bytes=data;
		top=data.length;
		offset=0;
	}
	/** 按指定的字节数组构造一个字节缓存对象 */
	public ByteBuffer(byte[] data,int index,int length)
	{
		if(data==null)
			throw new IllegalArgumentException(getClass().getName()
				+" <init>, null data");
		if(index<0||index>data.length)
			throw new IllegalArgumentException(getClass().getName()
				+" <init>, invalid index:"+index);
		if(length<0||data.length<index+length)
			throw new IllegalArgumentException(getClass().getName()
				+" <init>, invalid length:"+length);
		bytes=data;
		top=index+length;
		offset=index;
	}
	/* properties */
	/** 得到字节缓存的容积 */
	public int capacity()
	{
		return bytes.length;
	}
	/** 设置字节缓存的容积，只能扩大容积 */
	public void setCapacity(int len)
	{
		int c=bytes.length;
		if(len<=c) return;
		for(;c<len;c=(c<<1)+1)
			;
		byte[] temp=new byte[c];
		System.arraycopy(bytes,0,temp,0,top);
		bytes=temp;
	}
	/** 得到字节缓存的长度 */
	public int top()
	{
		return top;
	}
	/** 设置字节缓存的长度 */
	public void setTop(int top)
	{
		if(top<offset)
			throw new IllegalArgumentException(this+" setTop, invalid top:"
				+top);
		if(top>bytes.length) setCapacity(top);
		this.top=top;
	}
	/** 得到字节缓存的偏移量 */
	public int offset()
	{
		return offset;
	}
	/** 设置字节缓存的偏移量 */
	public void setOffset(int offset)
	{
		if(offset<0||offset>top)
			throw new IllegalArgumentException(this
				+" setOffset, invalid offset:"+offset);
		this.offset=offset;
	}
	/** 得到字节缓存的使用长度 */
	public int length()
	{
		return top-offset;
	}
	/** 得到字节缓存的字节数组，一般使用toArray()方法 */
	public byte[] getByteArray()
	{
		return bytes;
	}
	/* methods */
	/* byte methods */
	/** 得到指定偏移位置的字节 */
	public byte read(int pos)
	{
		return bytes[pos];
	}
	/** 设置指定偏移位置的字节 */
	public void write(int b,int pos)
	{
		bytes[pos]=(byte)b;
	}
	/* read methods */
	/**
	 * 按当前偏移位置读入指定的字节数组
	 * 
	 * @param data 指定的字节数组
	 * @param pos 指定的字节数组的起始位置
	 * @param len 读入的长度
	 */
	public void read(byte[] data,int pos,int len)
	{
		System.arraycopy(bytes,offset,data,pos,len);
		offset+=len;
	}
	/** 读出一个布尔值 */
	public boolean readBoolean()
	{
		return (bytes[offset++]!=0);
	}
	/** 读出一个字节 */
	public byte readByte()
	{
		return bytes[offset++];
	}
	/** 读出一个无符号字节 */
	public int readUnsignedByte()
	{
		return bytes[offset++]&0xff;
	}
	/** 读出一个字符 */
	public char readChar()
	{
		return (char)readUnsignedShort();
	}
	/** 读出一个短整型数值 */
	public short readShort()
	{
		return (short)readUnsignedShort();
	}
	/** 读出一个无符号的短整型数值 */
	public int readUnsignedShort()
	{
		int pos=offset;
		offset+=2;
		return (bytes[pos+1]&0xff)+((bytes[pos]&0xff)<<8);
	}
	/** 读出一个整型数值 */
	public int readInt()
	{
		int pos=offset;
		offset+=4;
		return (bytes[pos+3]&0xff)+((bytes[pos+2]&0xff)<<8)
			+((bytes[pos+1]&0xff)<<16)+((bytes[pos]&0xff)<<24);
	}
	/** 读出一个浮点数值 */
	public float readFloat()
	{
		return Float.intBitsToFloat(readInt());
	}
	/** 读出一个长整型数值 */
	public long readLong()
	{
		int pos=offset;
		offset+=8;
		return (bytes[pos+7]&0xffL)+((bytes[pos+6]&0xffL)<<8)
			+((bytes[pos+5]&0xffL)<<16)+((bytes[pos+4]&0xffL)<<24)
			+((bytes[pos+3]&0xffL)<<32)+((bytes[pos+2]&0xffL)<<40)
			+((bytes[pos+1]&0xffL)<<48)+((bytes[pos]&0xffL)<<56);
	}
	/** 读出一个双浮点数值 */
	public double readDouble()
	{
		return Double.longBitsToDouble(readLong());
	}
	/**
	 * 读出动态长度， 数据大小采用动态长度，整数类型下，最大为512M
	 * 1xxx,xxxx表示（0~0x80） 0~128B
	 * 01xx,xxxx,xxxx,xxxx表示（0~0x4000） 0~16K
	 * 001x,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx表示（0~0x20000000）
	 * 0~512M
	 */
	public int readLength()
	{
		int n=bytes[offset]&0xff;
		if(n>=0x80)
		{
			offset++;
			return n-0x80;
		}
		else if(n>=0x40)
			return readUnsignedShort()-0x4000;
		else if(n>=0x20)
			return readInt()-0x20000000;
		else
			throw new IllegalArgumentException(this
				+" readLength, invalid number:"+n);
	}
	/** 读出一个指定长度的字节数组，可以为null */
	public byte[] readData()
	{
		int len=readLength()-1;
		if(len<0) return null;
		if(len>MAX_DATA_LENGTH)
			throw new IllegalArgumentException(this
				+" readData, data overflow:"+len);
		byte[] data=new byte[len];
		read(data,0,len);
		return data;
	}
	/**读出一个短字节数组，长度不超过254 */
	public byte[] readShortData(){
		int len=readUnsignedByte();
		if(len==255) return null;
		byte[] data=new byte[len];
		if(len!=0) read(data,0,len);
		return data;
	}
	/**读出一个指定长度的字符串 */
	public String readString(int len){
		byte[] data=new byte[len];
		if(len==0) return "";
		read(data,0,len);
		return new String(data);
	}
	/**读出一个短字符串，长度不超过254 */
	public String readShortString(){
		int len=readUnsignedByte();
		if(len==255) return null;
		return readString(len);
	}
	/**读出一个字符串，长度不超过65534 */
	public String readString(){
		int len=readUnsignedShort();
		if(len==65535) return null;
		return readString(len);
	}
	/** 读出一个指定长度和编码类型的字符串 */
	public String readUTF(String charsetName)
	{
		int len=readLength()-1;
		if(len<0) return null;
		if(len>MAX_DATA_LENGTH)
			throw new IllegalArgumentException(this
				+" readUTF, data overflow:"+len);
		byte[] data=new byte[len];
		read(data,0,len);
		if(charsetName==null) return new String(data);
		try
		{
			return new String(data,charsetName);
		}
		catch(Exception e)
		{
			throw new IllegalArgumentException(this
				+" readUTF, invalid charsetName:"+charsetName);
		}
	}
	/** 读出一个指定长度的utf字符串 */
	public String readUTF()
	{
		int len=readLength()-1;
		if(len<0) return null;
		if(len==0) return "";
		if(len>MAX_DATA_LENGTH)
			throw new IllegalArgumentException(this
				+" readUTF, data overflow:"+len);
		StringBuffer sb=new StringBuffer(len);
		int pos=ByteKit.readUTF(bytes,offset,len,sb);
		if(pos>0)
			throw new IllegalArgumentException(this
				+" readUTF, format err, len="+len+", pos:"+pos);
		offset+=len;
		return sb.toString();
	}
	/* write methods */
	/**
	 * 写入指定字节数组
	 * 
	 * @param data 指定的字节数组
	 * @param pos 指定的字节数组的起始位置
	 * @param len 写入的长度
	 */
	public void write(byte[] data,int pos,int len)
	{
		if(bytes.length<top+len) setCapacity(top+len);
		System.arraycopy(data,pos,bytes,top,len);
		top+=len;
	}
	/** 写入一个布尔值 */
	public void writeBoolean(boolean b)
	{
		if(bytes.length<top+1) setCapacity(top+CAPACITY);
		bytes[top++]=(byte)(b?1:0);
	}
	/** 写入一个字节 */
	public void writeByte(int b)
	{
		if(bytes.length<top+1) setCapacity(top+CAPACITY);
		bytes[top++]=(byte)b;
	}
	/** 写入一个字符 */
	public void writeChar(int c)
	{
		writeShort(c);
	}
	/** 写入一个短整型数值 */
	public void writeShort(int s)
	{
		int pos=top;
		if(bytes.length<pos+2) setCapacity(pos+CAPACITY);
		bytes[pos]=(byte)(s>>>8);
		bytes[pos+1]=(byte)s;
		top+=2;
	}
	/**在指定位置写入一个短整型数值，length不变 */
	public void writeShort(int s,int pos){
		if(bytes.length<pos+2) setCapacity(pos+CAPACITY);
		bytes[pos]=(byte)(s>>>8);
		bytes[pos+1]=(byte)s;
	}
	/** 写入一个整型数值 */
	public void writeInt(int i)
	{
		int pos=top;
		if(bytes.length<pos+4) setCapacity(pos+CAPACITY);
		bytes[pos]=(byte)(i>>>24);
		bytes[pos+1]=(byte)(i>>>16);
		bytes[pos+2]=(byte)(i>>>8);
		bytes[pos+3]=(byte)i;
		top+=4;
	}
	/**在指定位置写入一个整型数值，length不变 */
	public void writeInt(int i,int pos){
		if(bytes.length<pos+4) setCapacity(pos+CAPACITY);
		bytes[pos]=(byte)(i>>>24);
		bytes[pos+1]=(byte)(i>>>16);
		bytes[pos+2]=(byte)(i>>>8);
		bytes[pos+3]=(byte)i;
	}
	/** 写入一个浮点数值 */
	public void writeFloat(float f)
	{
		writeInt(Float.floatToIntBits(f));
	}
	/** 写入一个长整型数值 */
	public void writeLong(long l)
	{
		int pos=top;
		if(bytes.length<pos+8) setCapacity(pos+CAPACITY);
		bytes[pos]=(byte)(l>>>56);
		bytes[pos+1]=(byte)(l>>>48);
		bytes[pos+2]=(byte)(l>>>40);
		bytes[pos+3]=(byte)(l>>>32);
		bytes[pos+4]=(byte)(l>>>24);
		bytes[pos+5]=(byte)(l>>>16);
		bytes[pos+6]=(byte)(l>>>8);
		bytes[pos+7]=(byte)l;
		top+=8;
	}
	/** 写入一个双浮点数值 */
	public void writeDouble(double d)
	{
		writeLong(Double.doubleToLongBits(d));
	}
	/** 写入动态长度 */
	public void writeLength(int len)
	{
		if(len>=0x20000000||len<0)
			throw new IllegalArgumentException(this
				+" writeLength, invalid len:"+len);
		if(len>=0x4000)
			writeInt(len+0x20000000);
		else if(len>=0x80)
			writeShort(len+0x4000);
		else
			writeByte(len+0x80);
	}
	/** 写入一个字节数组，可以为null */
	public void writeData(byte[] data)
	{
		writeData(data,0,(data!=null)?data.length:0);
	}
	/** 写入一个字节数组，可以为null */
	public void writeData(byte[] data,int pos,int len)
	{
		if(data==null)
		{
			writeLength(0);
			return;
		}
		writeLength(len+1);
		write(data,pos,len);
	}
	/** 写入一个字符串，可以为null */
	public void writeString(String str)
	{
		writeUTF(str,null);
	}
	/** 写入一个字符串，以指定的字符进行编码 */
	public void writeUTF(String str,String charsetName)
	{
		if(str==null)
		{
			writeLength(0);
			return;
		}
		byte[] data;
		if(charsetName!=null)
		{
			try
			{
				data=str.getBytes(charsetName);
			}
			catch(Exception e)
			{
				throw new IllegalArgumentException(this
					+" writeUTF, invalid charsetName:"+charsetName);
			}
		}
		else
			data=str.getBytes();
		writeLength(data.length+1);
		write(data,0,data.length);
	}
	/** 写入一个utf字符串，可以为null */
	public void writeUTF(String str)
	{
		writeUTF(str,0,(str!=null)?str.length():0); 
	}
	/** 写入一个utf字符串中指定的部分，可以为null */
	public void writeUTF(String str,int index,int length)
	{
		if(str==null)
		{
			writeLength(0);
			return;
		}
		int len=ByteKit.getUTFLength(str,index,length);
		writeLength(len+1);
		int pos=top;
		if(bytes.length<pos+len) setCapacity(pos+len);
		ByteKit.writeUTF(str,index,length,bytes,pos);
		top+=len;
	}
	/** 检查是否为相同类型的实例 */
	public boolean checkClass(Object obj)
	{
		return (obj instanceof ByteBuffer);
	}
	/**在指定位置写入一个字节，length不变 */
	public void writeByte(int b,int pos){
		if(bytes.length<pos+1) setCapacity(pos+CAPACITY);
		bytes[pos]=(byte)b;
	}
	/**得到字节缓存当前长度的字节数组 */
	public byte[] toArray(){
		byte[] data=new byte[top-offset];
		System.arraycopy(bytes,offset,data,0,data.length);
		return data;
	}
	/** 清除字节缓存对象 */
	public void clear()
	{
		top=0;
		offset=0;
	}
	/* common methods */
	public int hashCode()
	{
		int hash=17;
		for(int i=top-1;i>=0;i--)
			hash=65537*hash+bytes[i];
		return hash;
	}
	public boolean equals(Object obj)
	{
		if(this==obj) return true;
		if(!checkClass(obj)) return false;
		ByteBuffer bb=(ByteBuffer)obj;
		if(bb.top!=top) return false;
		if(bb.offset!=offset) return false;
		for(int i=top-1;i>=0;i--)
		{
			if(bb.bytes[i]!=bytes[i]) return false;
		}
		return true;
	}
	public String toString()
	{
		return super.toString()+"["+top+","+offset+","+bytes.length+"] ";
	}
}